///////////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2007-2009 ILOG, S.A.
//  All Rights Reserved.
//  The following is ILOG Source Code.  No modifications may be made to the  
//  ILOG Source Code.  Any usage of the ILOG Source Code is subject to 
//  the terms and conditions of the ILOG End User License Agreement   
//  applicable to this ILOG software product.
//
///////////////////////////////////////////////////////////////////////////////

package ilog.gauges.rectangular.renderers
{
  import flash.display.Graphics;
  import flash.geom.Rectangle;
  
  import ilog.gauges.gaugesClasses.rectangular.RectangularValueRenderer;
  import ilog.utils.CSSUtil;
  
  import mx.graphics.IFill;
  import mx.graphics.IStroke;
  import mx.graphics.SolidColor;
  import mx.styles.CSSStyleDeclaration;
  
  /**
   * Specifies the stroke for the bar.
   * This style must be an instance of an implementation of the <code>IStroke</code> interface.  
   * 
   * @default undefined
   */
  [Style(name="stroke", type="mx.graphics.IStroke", inherit="no")]

  /**
   * Specifies the fill for the bar.
   *
   * This style must be an instance of an implementation of the <code>IFill</code> interface.
   * 
   * @default 0xFF0000
   */
  [Style(name="fill", type="mx.graphics.IFill", inherit="no")]  
  
  /**
   * A <code>RectangularBarRenderer</code> is a visual element that represents a 
   * value on a scale by using a bar from the minimum position of the corresponding 
   * scale to the position corresponding to the value. 
   * 
   * The bar is filled with the <code>IFill</code> specified in the <code>fill</code>
   * style property. The definition rectangle used for the <code>fill</code>
   * goes from the minimum position to the maximum position of the scale. This 
   * means that, when you use a <code>LinearGradient</code> from green to red, the 
   * red end value (<code>ratio="1"</code>) is only visible when the value of the 
   * <code>RectangularBarRenderer</code> corresponds to the maximum of the
   * scale.
   *
   * @mxml
   *  
   * <p>The <code>&lt;ilog:RectangularBarRenderer&gt;</code> tag inherits all the properties
   * of its parent classes and adds the following properties:</p>
   *  
   * <pre>
   * &lt;ilog:RectangularBarRenderer
   *   <strong>Properties</strong>
   *   rounded="false"
   *   radius="2"
   * 
   *   <strong>Styles</strong>
   *   fill="0xFF0000"
   *   stroke="<i>No default</i>" 
   * /&gt;
   * </pre>
   *    
   * @includeExample examples/RectangularBarRendererExample.mxml -noswf
   */  
  public class RectangularBarRenderer extends RectangularValueRenderer
  {
    private static var stylesInited:Boolean = initStyles(); 

    private static function initStyles():Boolean
    {
      var nStyle:CSSStyleDeclaration =
        CSSUtil.createSelector("RectangularBarRenderer");   
            
      nStyle.defaultFactory = function():void  {
        this.fill = new SolidColor(0xff0000);
      }

      return true;
    }    
    
    /**
     * Constructor.
     */ 
    public function RectangularBarRenderer() 
    {     
    }
    
    private var _rounded:Boolean = false;
    
    [Inspectable(category="Gauge")]    
    
    /**
     * Specifies whether the rectangle is drawn with rounded corners or not.
     * 
     * @default false
     * @see #radius
     */
    public function get rounded():Boolean
    {
      return _rounded;
    }
    
    /**
     * @private
     */
    public function set rounded(value:Boolean):void
    {
      _rounded = value;
      invalidateDisplayList();
    }            
    
    private var _radius:Number = 2;
    
    [Inspectable(category="Gauge")]    
    
    /**
     * When <code>rounded</code> is <code>true</code>, specifies the radius of 
     * the rounded corners. This property has no effect if <code>rounded</code>
     * is <code>false</code>.
     * 
     * @default 2
     */
    public function get radius():Number
    {
      return _radius;
    }
    
    /**
     * @private
     */
    public function set radius(value:Number):void
    {
      _radius = value;
      invalidateDisplayList() 
    }    

    /**
     * Draws the bar. Subclasses can redefine this method to draw a different
     * bar.
     * 
     * @param graphics The <code>Graphic</code> to draw into.
     * @param horizontal Specifies whether the bar must be horizontal or vertical.
     * @param x The <code>x</code> position of the bar bounds.
     * @param y The <code>y</code> position of the bar bounds.
     * @param width The width of the bar bounds.
     * @param height The height of the bar bounds.
     * @param rc The definition rectangle to be used for the fill.
     * @param fill The <code>IFill</code> to be used to fill the bar.
     * @param stroke The <code>IStroke</code> to be used to stroke the bar.
     */    
    protected function drawBar(graphics:Graphics, horizontal:Boolean,
                               x:Number, y:Number, width:Number, height:Number,
                               rc:Rectangle, fill:IFill, stroke:IStroke):void         
    {
       if (stroke != null) {
         stroke.apply(graphics);
       } 
       if (fill != null) {
         fill.begin(graphics, rc);
       }
       if (!rounded)
         graphics.drawRect(x, y, width, height);
       else
         graphics.drawRoundRect(x, y, width, height, 2*radius, 2*radius);
       if (fill != null) {
         fill.end(graphics);
       }    
    } 
 
    /**
     * Draws the bar by calling <code>drawBar</code>.     
     *
     * @param unscaledWidth Specifies the width, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleX</code> property of the component.
     *
     * @param unscaledHeight Specifies the height, in pixels, of the component
     * in the component's coordinates, regardless of the value of the
     * <code>scaleY</code> property of the component.
     * 
     * @see #drawBar()
     */
    protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
    {     
      // call super in case we are the master to update the scale     
      super.updateDisplayList(unscaledWidth, unscaledHeight);

      var endPos:Number = isNaN(transitionPosition) ? scale.positionForValue(value) : 
                                                      transitionPosition;
      var maxPos:Number = scale.offset + scale.length;
      var startPos:Number = scale.offset;
      if (gauge.direction == "horizontal") {
        drawBar(graphics, true, startPos, 0, endPos - startPos, unscaledHeight,
                new Rectangle(startPos, 0, maxPos - startPos, unscaledHeight),
                getStyle("fill"), getStyle("stroke"));
      } else {
        // vertical
        drawBar(graphics, false, 0, unscaledHeight - endPos, unscaledWidth, endPos - startPos,
                new Rectangle(0, unscaledHeight - maxPos, unscaledWidth, maxPos - startPos), 
                getStyle("fill"), getStyle("stroke"));        
      }      
    }    
  }
}
